ALB + Cognito認証で付与されるユーザー情報をEC2サイドから眺めてみる
ALBはCognitoと組み合わせることで、簡単にWebサーバーの認証機能を実現できます。超便利。
ALBとCognitoを組み合わせた認証については、弊社ブログで解説しているのでこちらを御覧ください。
本ブログでは、ここからもう一歩踏み込んで、ALBが認証後EC2に何を渡しているのか?(EC2はユーザー情報をどう受けとっているのか?)を眺めてみます。
構成図
こんな感じのシンプルな構成を作ります。ALBへのアクセス時に、Cognitoと連携して認証を行います。CognitoでログインできたユーザーだけがEC2上のコンテンツにアクセスできます。
ALB + Cognito認証のおさらい
ALB + Cognitoの認証がどういったフローで動いているか、ここで一度おさらいしましょう。 OIDC認証がわかっていると、似たような動作をしているので理解しやすいです。 だいたい、ALBがリライング・パーティ、CognitoがIDプロバイダの動きをしています。
フローを図にするとこんな感じです。
まずは、ALBに対してアクセスすると、Cognitoのログイン画面にリダイレクトされます。(フロー図の1〜4)
ログイン画面でID,パスワードを入力してログインすると、認証レスポンスがALBのコールバックURLにリダイレクトされます。(フロー図の5〜7)
その後、ALBとCognito間の裏側でトークンリクエストやIDトークンの検証をして(フロー図の8〜10)、ユーザークレームをCognitoから取得して(フロー図の11、12)、認証が完了したらもともとアクセスをしていたURLへリダイレクトして(フロー図の13〜14)、ユーザー情報をヘッダーに付与してEC2へ転送してログイン後の画面が表示される(フロー図の15〜17)といったフローになっています。
このフローを経て、ユーザーの認証に成功すると、ロードバランサは次のHTTPヘッダを追加してEC2に渡します。(フロー図の15)
x-amzn-oidc-accesstoken トークンエンドポイントからのアクセストークン (プレーンテキスト)。
x-amzn-oidc-identity ユーザー情報エンドポイントからの件名フィールド (sub) (プレーンテキスト)。
x-amzn-oidc-data ユーザークレーム (JSON ウェブトークン (JWT) 形式)
参考:ユーザークレームのエンコードと署名の検証 | Application Load Balancer を使用してユーザーを認証する - Elastic Load Balancing
この追加されたHTTPヘッダ(ユーザー情報)をEC2サイドから覗いてみます。
DockerでPHPを動かす
EC2が受け取るHTTPリクエストヘッダを覗きたいので、phpinfoを使って、HTTPリクエストヘッダをべろっと出してみます。
PHPの環境をまともに作るのは面倒くさいので、Dockerを使ってさくっと作ります。
EC2インスタンスにSSHログインして、Dockerをインストールしていきます。
$ sudo yum install docker -y $ sudo service docker start $ sudo usermod -a -G docker ec2-user $ sudo systemctl enable docker
phpinfoを表示するためのphpファイルを作ります。
$ mkdir /home/ec2-user/www $ chmod 755 /home/ec2-user/www $ echo "<?php phpinfo();" > /home/ec2-user/www/info.php
Dockerでphpを動かします。
$ docker run -d -p 8080:80 --name php -v /home/ec2-user/www:/var/www/html php:7.2-apache
ブラウザからALB経由でEC2へアクセスしてみると、べろっとHTTPリクエストヘッダをだすことができました。
EC2サイドからユーザー情報を眺めてみる
ALBに追加された次の3つのヘッダ情報が、どういう情報なのか実際に確認してみます。
- x-amzn-oidc-accesstoken:アクセストークン
- x-amzn-oidc-identity:ユーザーの一意の識別子 (UUID)
- x-amzn-oidc-data:ユーザークレーム (JWT)
-
ユーザークレームのエンコードと署名の検証 | Application Load Balancer を使用してユーザーを認証する - Elastic Load Balancing
x-amzn-oidc-accesstoken
x-amzn-oidc-accesstokenはアクセストークンです。
アクセストークンを利用すると、Cognitoからユーザー情報を取得できます。 CogintoのUSERINFOエンドポイントは、アクセストークンを利用して認証されたユーザーに関する情報を返します。
よって、次のようにヘッダを利用してアクセストークンを渡すことで、認証されたユーザーのユーザー情報を受け取ることができます。
$ ACCESS_TOKEN=<<x-amzn-oidc-accesstokenをコピー&ペースト>> $ COGNITO_URL=<<Cognitoドメインをコピー&ペースト>> $ curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \ ${COGNITO_URL}/oauth2/userInfo { "sub": "248289761001", "name": "Jane Doe", "given_name": "Jane", "family_name": "Doe", "preferred_username": "j.doe", "email": "janedoe@example.com" }
ちなみにCognitoドメインは、Cognitoユーザープールの画面で参照できます。
x-amzn-oidc-identity
x-amzn-oidc-identityはユーザーの一意の識別子 (UUID)で、Cognitoのsubクレームです。
Cognitoでログインしたユーザーのユーザー画面と比較してみると、確かに一致していることがわかります。
x-amzn-oidc-data
x-amzn-oidc-dataはユーザークレーム(ユーザー情報)です。
ユーザークレームがJWT形式で保持されています。JWT形式ではありますが、IDトークンではありません。 JWT形式のため、ペイロード部分を切り出してbase64デコードすると、ユーザー情報の内容を確認することができます。
$ OIDC_DATA=<<x-amzn-oidc-dataをコピー&ペースト>> $ echo $OIDC_DATA | cut -d'.' -f 2 | base64 -D { "sub": "1234567890", "name": "name", "email": "alias@example.com", ... }
終わりに
ALBとCognitoの認証をEC2サイドから見てみました。
ALBとCognitoの認証の動きを知ることで、アプリケーションのあるEC2側でユーザー情報がどうやって渡されるのかが理解できると思います。
本ブログがその際の理解の助けになれば幸いです。